/**
 * Copyright 2017 orivil Authors. All rights reserved.
 * Use of this source code is governed by a MIT-style
 * license that can be found at https://mit-license.org.
 */

package swagger

import (
	"bytes"
	"sort"
	"encoding/json"
)

// A relative path to an individual endpoint.
// The field name MUST begin with a slash. The path is appended to
// the basePath in order to construct the full URL.
// Path template(http://swagger.io/specification/#pathTemplating) is allowed.
type Paths map[string]*PathItem

type PathItem struct {
	// Allows for an external definition of this path item.
	// The referenced structure MUST be in the format of a
	// Path Item Object(http://swagger.io/specification/#pathItemObject).
	// If there are conflicts between the referenced definition and this
	// Path Item's definition, the behavior is undefined.
	Ref string `json:"$ref,omitempty"`

	// A definition of a GET operation on this path.
	Get *Operation `json:"get,omitempty"`

	// A definition of a PUT operation on this path.
	Put *Operation `json:"put,omitempty"`

	// A definition of a POST operation on this path.
	Post *Operation `json:"post,omitempty"`

	// A definition of a DELETE operation on this path.
	Delete *Operation `json:"delete,omitempty"`

	// A definition of a OPTIONS operation on this path.
	Options *Operation `json:"options,omitempty"`

	// A definition of a HEAD operation on this path.
	Head *Operation `json:"head,omitempty"`

	// A definition of a PATCH operation on this path.
	Patch *Operation `json:"patch,omitempty"`

	// A definition of a TRACE operation on this path.
	Trace *Operation `json:"trace,omitempty"`

	// A list of parameters that are applicable for all the operations described under this path.
	// These parameters can be overridden at the operation level, but cannot be removed there.
	// The list MUST NOT include duplicated parameters. A unique parameter is defined by a
	// combination of a name(http://swagger.io/specification/#parameterName) and
	// location(http://swagger.io/specification/#parameterIn).
	// The list can use the Reference Object(http://swagger.io/specification/#referenceObject) to
	// link to parameters that are defined at the
	// Swagger Object's parameters(http://swagger.io/specification/#swaggerParameters).
	// There can be one "body" parameter at most.
	Parameters Parameters `json:"parameters,omitempty"`
}

// 重定义 json 解析方法, 为 path 排序
func (ps Paths) MarshalJSON() (data []byte, err error) {
	buf := bytes.NewBuffer(nil)
	paths := make([]string, len(ps))
	idx := 0
	for key := range ps {
		paths[idx] = key
		idx++
	}
	sort.Strings(paths)
	buf.WriteString("{")
	idx--
	for i, path := range paths {
		buf.WriteString(`"`+path+`":`)
		data, err = json.Marshal(ps[path])
		if err != nil {
			return
		}
		buf.Write(data)
		if i != idx {
			buf.WriteRune(',')
		}
	}
	buf.WriteRune('}')
	data = buf.Bytes()
	return
}